#pragma once
#include <iostream>
#include <string>
#include <ctime>
#include <cstdarg>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>

#define LOG_SIZE 1024
#define DEFAULT_LOG_FILE_PATH "./log/"
#define DEFAULT_LOG_FILE_NAME "log"

//枚举 Log 等级
enum LogLevel{
    Info,
    Debug,
    Warning,
    Error,
    Fatal
};

//枚举输出方式
enum OutputWay{
    SCREEN = 1,
    SINGAL_FILE = 2,
    MULTIPLE_FILES = 3
};

class Logger{
public:
    //设置单例模式
    static Logger& GetInstance(){
        static Logger instance;
        return instance;
    }

    //设置输出方向
    void SetOutputWay(OutputWay set_output_way){
        output_way = set_output_way;
    }

    //重载括号运算符
    void operator()(LogLevel level, const char* format, ...){
        //获取时间戳
        time_t time_stamp = time(nullptr);
        //获取时间结构体
        struct tm* time_struct = localtime(&time_stamp);
        //设置LOG
        char log_head[LOG_SIZE] = {0};
        snprintf(log_head, sizeof(log_head), "[%s][%d-%d-%d %d:%d:%d]", LogLevelToString(level).c_str(), 
            time_struct->tm_year + 1900, time_struct->tm_mon + 1, time_struct->tm_mday,
            time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec
        );
        
        //读取可变参数
        va_list list;
        va_start(list, format);
        char log_client_in[LOG_SIZE] = {0};
        vsnprintf(log_client_in, sizeof(log_client_in), format, list);
        va_end(list);

        //合并
        char log_msg[LOG_SIZE * 2] = {0};
        snprintf(log_msg, sizeof(log_msg), "%s %s\n", log_head, log_client_in);

        //输出打印log_msg
        _OutputLog(level, log_msg);
    }

    //禁用拷贝构造函数与赋值函数
    Logger(const Logger&) = delete;
    Logger& operator =(const Logger&) = delete;

private:
    Logger(){
        output_way = SCREEN;
    };
    ~Logger(){}

    //输出方式
    OutputWay output_way;

    //Loglevel转String
    std::string LogLevelToString(LogLevel level) const{
        switch (level)
        {
        case Info: return "Info";
        case Debug: return "Debug";
        case Warning: return "Warning";
        case Error: return "Error";
        case Fatal: return "Fatal";
        default: return "Unkonw";
        }
    }

    //打印msg
    void _OutputLog(LogLevel level, const std::string& log_msg){
        std::string file_created("");
        int fd_ret = 0;

        switch (output_way)
        {
        case SCREEN:
            std::cout << log_msg;
        break;
        case SINGAL_FILE:
            //设置文件名
            file_created += DEFAULT_LOG_FILE_PATH;
            file_created += DEFAULT_LOG_FILE_NAME;
            file_created += ".txt";

            fd_ret = open(file_created.c_str(),O_WRONLY | O_CREAT | O_APPEND, 0664);
            if(fd_ret == -1) return;
            write(fd_ret, log_msg.c_str(), log_msg.size());
            close(fd_ret);
        break;
        case MULTIPLE_FILES:
            //设置文件名
            file_created += DEFAULT_LOG_FILE_PATH;
            file_created += DEFAULT_LOG_FILE_NAME;
            file_created += ".";
            file_created += LogLevelToString(level);
            file_created += ".txt";

            fd_ret = open(file_created.c_str(),O_WRONLY | O_CREAT | O_APPEND, 0664);
            if(fd_ret == -1) return;
            write(fd_ret, log_msg.c_str(), log_msg.size());
            close(fd_ret);
        break;
        }
    }  
};

//设置直接引用
#define Log Logger::GetInstance();